#include <iostream>
using std::cout;
using std::endl;
using std::string;

template <class T, int kCapacity = 10>
class Stack
{
public:
    Stack()
    : _top(-1)
    , _data(new T[kCapacity]())
    {
        cout << "Stack()" << endl;
    }
    ~Stack(){
        if(_data){
            delete [] _data;
            _data = nullptr;
        }
        cout << "~Stack()" << endl;
    }
    bool empty() const;
    bool full() const;
    void push(const T &);
    void pop();
    T top();
private:
    int _top;
    T * _data;
};


template <class T, int kCapacity>
bool Stack<T,kCapacity>::empty() const{
    return _top == -1;
}


template <class T, int kCapacity>
bool Stack<T,kCapacity>::full() const{
    return _top == kCapacity - 1;
}


template <class T, int kCapacity>
void Stack<T,kCapacity>::push(const T & t){
    if(!full()){
        _data[++_top] = t;
    }else{
        cout << "Stack is full!" << endl;
    }
}

template <class T, int kCapacity>
void Stack<T,kCapacity>::pop(){
    if(!empty()){
        --_top;
    }else{
        cout << "Stack is empty!" << endl;
    }
}


template <class T, int kCapacity>
T Stack<T,kCapacity>::top(){
    return _data[_top];
}

void test0(){

    Stack<int,20> stack2;
    Stack<double,30> stack3;

    Stack<string> stack; 
    cout << "Is stack empty? " << stack.empty() << endl;
    stack.push(string(3,'a'));
    cout << "Is stack empty? " << stack.empty() << endl;

    for(int idx = 1; idx < 11; ++idx){
        stack.push(string(3, 'a' + idx));
    }

    cout << "Is stack full? " <<  stack.full() << endl;

    while(!stack.empty()){
        cout << stack.top() << " ";
        stack.pop();
    }
    cout << endl;
    cout << "Is stack full? " <<  stack.full() << endl;
    cout << "Is stack empty? " << stack.empty() << endl;
    
}

int main(void){
    test0();
    return 0;
}
